﻿
using System.ComponentModel.DataAnnotations;
using System;
using System.ComponentModel;
using System.Reflection;
using HBCode.BusinessLogic.Validations;
using System.Text.RegularExpressions;
namespace HBCode.BusinessLogic.Base
{
    public abstract class EntityBase : PropertyNotifier, ICloneable, IDataErrorInfo
    {
        private bool _isExists = true;
        [NotMappedAttribute]
        public bool IsExists
        {
            get
            {
                return _isExists;
            }
            set
            {
                if (_isExists == value)
                    return;
                OnPropertyChanging("IsExists");
                _isExists = value;
                OnPropertyChanged("IsExists");
            }
        }

        private bool _isSelected;
        [NotMappedAttribute]
        public bool IsSelected
        {
            get { return _isSelected; }
            set
            {
                if (_isSelected == value)
                    return;
                this.OnPropertyChanging("IsSelected");
                _isSelected = value;
                this.OnPropertyChanged("IsSelected");
            }
        }

        private bool _isDirty;
        [NotMappedAttribute]
        public bool IsDirty
        {
            get
            {
                return _isDirty;
            }
            set
            {
                if (_isDirty == value)
                    return;
                OnPropertyChanging("IsDirty");
                _isDirty = value;
                OnPropertyChanged("IsDirty");
            }
        }

        [NotMappedAttribute]
        public virtual bool IsValid
        {
            get
            {
                return string.IsNullOrWhiteSpace(Error);
            }
        }

        object ICloneable.Clone()
        {
            return Clone();
        }

        public EntityBase Clone()
        {
            return (EntityBase)this.MemberwiseClone();
        }

        public TEntityBase Clone<TEntityBase>()
        {
            return (TEntityBase)this.MemberwiseClone();
        }

        [NotMappedAttribute]
        public string Error { get; set; }

        public string this[string columnName]
        {
            get { return Error = this.GetColumnValidated(columnName); }
        }

        public virtual string GetColumnValidated(string columnName)
        {
            PropertyInfo info = this.GetType().GetProperty(columnName);
            if (info != null)
            {
                string value = Convert.ToString(info.GetValue(this, null));
                object[] customattributes = info.GetCustomAttributes(typeof(ValidateAttribute), false);
                if (customattributes != null && customattributes.Length > 0)
                {
                    ValidateAttribute validateAttribute = customattributes[0] as ValidateAttribute;
                    if (validateAttribute.Type != ValidateType.Optional && validateAttribute.IsRequired && string.IsNullOrWhiteSpace(value))
                        return "Validation.RequiredFieldMissing";

                    switch (validateAttribute.Type)
                    {
                        case ValidateType.CreditCard:
                            validateAttribute.RegexExpression = RegExCreditCard;
                            validateAttribute.ErrorMessage = "Validation.CreditCard";
                            break;
                        case ValidateType.Date:
                            validateAttribute.RegexExpression = RegExDate;
                            validateAttribute.ErrorMessage = "Validation.Date";
                            break;
                        case ValidateType.Email:
                            validateAttribute.RegexExpression = RegExEmail;
                            validateAttribute.ErrorMessage = "Validation.Email";
                            break;
                        case ValidateType.NumericOnly:
                            validateAttribute.RegexExpression = RegExNumber;
                            validateAttribute.ErrorMessage = "Validation.Number";
                            break;
                        case ValidateType.Phone:
                            validateAttribute.RegexExpression = RegExPhone;
                            validateAttribute.ErrorMessage = "Validation.Phone";
                            break;
                        case ValidateType.Text:
                            validateAttribute.RegexExpression = RegExText;
                            validateAttribute.ErrorMessage = "Validation.Text";
                            break;
                        case ValidateType.Url:
                            validateAttribute.RegexExpression = RegExWebsite;
                            validateAttribute.ErrorMessage = "Validation.Url";
                            break;
                    }

                    if (!string.IsNullOrWhiteSpace(validateAttribute.RegexExpression))
                    {
                        if (!validateAttribute.IsRequired && string.IsNullOrEmpty(value))
                            return null;
                        Regex reg = new Regex(validateAttribute.RegexExpression);
                        if (!reg.IsMatch(value))
                            return validateAttribute.ErrorMessage;
                    }
                }
            }
            return null;
        }

        public const string RegExNumber = @"^\d+$";
        public const string RegExText = @"^\w+$";
        public const string RegExPhone = @"(\d-)?(\d{3}-)?\d{3}-\d{4}";
        public const string RegExEmail = @"^([a-zA-Z0-9_\.\-])+\@(([a-zA-Z0-9\-])+\.)+([a-zA-Z0-9]{2,4})+$";
        public const string RegExWebsite = @"^(|https?:\/\/[\w\-_]+(\.[\w\-_]+)+([\w\-\.,@?^=%&amp;:/~\+#]*[\w\-\@?^=%&amp;/~\+#])?)$";
        public const string RegExDate = @"[0-9]{2}/[0-9]{2}/[0-9]{4}";
        public const string RegExCreditCard = @"^4[0-9]{12}(?:[0-9]{3})?$";
    }
}
